package cn.tannn.cat.file.sdk.core.qiniu;

import cn.tannn.cat.file.sdk.OssOperateAPI;
import cn.tannn.cat.file.sdk.api.UploadFile;
import cn.tannn.cat.file.sdk.bean.FileIndex;
import cn.tannn.cat.file.sdk.bean.FileStorage;
import cn.tannn.cat.file.sdk.config.QiNiuConfig;
import cn.tannn.cat.file.sdk.constants.OSSConstants;
import cn.tannn.cat.file.sdk.core.OssCache;
import cn.tannn.cat.file.sdk.exception.FileException;
import cn.tannn.cat.file.sdk.utils.AboutFileUtil;
import cn.tannn.cat.file.sdk.utils.FileUtils;
import cn.tannn.cat.file.sdk.utils.ResponseFile;
import com.qiniu.http.Response;
import jakarta.servlet.http.HttpServletResponse;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
import java.util.UUID;

/**
 * 七牛文件操作
 *
 * @author <a href="https://tannn.cn/">tnnn</a>
 * @version V1.0
 * @date 2024/4/5 下午9:21
 */
@Service
@Slf4j
public class QiNiuOperate implements OssOperateAPI {

    @Override
    public FileIndex uploadFile(UploadFile upload, FileStorage storage) throws IOException {
        QiNiuConfig qiNiuConfig = storage.getConfig().toJavaObject(QiNiuConfig.class);
        QiNiuClient qiNiuClient = OssCache.qiNiuClientCache.get(storage.getId());
        String originalName = upload.getFile().getOriginalFilename();
        // 文件类型后缀 如 jpg png
        if(originalName== null){
            originalName = UUID.randomUUID().toString();
        }
        String suffixDot = AboutFileUtil.getFileSuffixDot(originalName);
        // 新文件名
        String freshName;
        if (StringUtils.isNotBlank(upload.getFileName())) {
            freshName = upload.getFileName().trim() + suffixDot;
        } else {
            freshName = originalName;
        }
        String childFolder = Objects.isNull(upload.getChildFolder()) ? "" : upload.getChildFolder();
        String uploadPath =  childFolder + freshName;
        // 文件全路径（http ps:七牛的访问地址不带bucket
        String url =  qiNiuConfig.getBrowseUrl()+"/"+uploadPath;

        Response response = qiNiuClient.getUploadManager().put(upload.getFile().getInputStream(),
                uploadPath,
                QiNiuUtils.getUploadToken(upload.getBucket(), qiNiuClient.getAuth()),
                null,
                null);
        String bucketPath = upload.getBucket() + OSSConstants.PATH_SEPARATOR + uploadPath;
        log.debug("七牛文件上次返回内容 ===> {}", response);
        FileIndex fileStorage = new FileIndex();
        fileStorage.setStorageId(storage.getId());
        fileStorage.setStorage(storage.getStorage());
        fileStorage.setOriginalName(originalName);
        fileStorage.setFreshName(freshName);
        fileStorage.setPath(uploadPath);
        fileStorage.setSubPath(uploadPath);
        fileStorage.setUrl(url);
        // 七牛的访问地址不带bucket,所以个 path 一样
        fileStorage.setUrlSuffix(uploadPath);
        fileStorage.setBucket(upload.getBucket());
        fileStorage.setBucketPath(bucketPath);
        fileStorage.setType(upload.getFile().getContentType());
        fileStorage.setSizeUnit(AboutFileUtil.getFileSizeUnit(upload.getFile().getSize()));
        fileStorage.setSize(upload.getFile().getSize());
        return fileStorage;
    }

    @Override
    public boolean removeFile(FileIndex index) {
        try {
            OssCache.qiNiuClientCache.get(index.getStorageId())
                    .getBucketManager()
                    .delete(index.getBucket(), index.getPath());
            return true;
        } catch (Exception e) {
            log.error("七牛删除失败：index id : {} , URL: {}", index.getId(), index.getUrl(), e);
            throw FileException.specialMessage("文件删除失败");
        }
    }


    @SneakyThrows
    @Override
    public void downloadFile(HttpServletResponse response, FileIndex index) {
        QiNiuClient qiNiuClient = OssCache.qiNiuClientCache.get(index.getStorageId());
        //去掉地址地址中的特殊符号
        String urlString = URLEncoder.encode(index.getPath(), StandardCharsets.UTF_8).replaceAll("\\+", "%20");
        String downLoadStr = index.getUrl().replaceAll(index.getPath(), urlString);
        //调用privateDownloadUrl方法生成下载链接,第二个参数可以设置Token的过期时间
        String downloadRUL = qiNiuClient.getAuth().privateDownloadUrl(downLoadStr, 3600);
        try {
            URL url = new URL(downloadRUL);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            HttpServletResponse downResponse = ResponseFile.customResponse(response
                    , index.getType(), index.getFreshName());
            //设置文件大小 [url.openConnection().getContentLength()]
            downResponse.setHeader("Content-Length", String.valueOf(index.getSize()));
            IOUtils.copy(conn.getInputStream(), downResponse.getOutputStream());
        } catch (Exception e) {
            log.error("七牛文件下载失败：index id : {} , URL: {}", index.getId(), index.getUrl(), e);
        }
    }

    @SneakyThrows
    @Override
    public String previewFile(FileIndex index, Integer expires) {
        if (index == null) {
            throw new IllegalArgumentException("文件索引不能为空");
        }
        QiNiuClient qiNiuClient = OssCache.qiNiuClientCache.get(index.getStorageId());
        //去掉地址地址中的特殊符号
        String urlString = URLEncoder.encode(index.getPath(), StandardCharsets.UTF_8).replaceAll("\\+", "%20");
        String downLoadStr = index.getUrl().replaceAll(index.getPath(), urlString);
        //调用privateDownloadUrl方法生成下载链接,第二个参数可以设置Token的过期时间
        return qiNiuClient.getAuth().privateDownloadUrl(downLoadStr, FileUtils.defExpires(expires));
    }
}
